
/*
Copyright 2009 Peter Ekler, Akos Ludanyi, Budapest University of Technology and Economics, Department of Automation and Applied Informatics, Applied Mobile Research Group (AMORG) http://amorg.aut.bme.hu

This file is part of MobTorrent.

MobTorrent is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

MobTorrent is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with MobTorrent.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ui;

import Logger.MTLogger;
import Settings.MTErrorCodes;
import TorrentEngine.MTOpenTorrentResult;
import TorrentEngine.MTStringFormatter;
import TorrentEngine.MTTorrent;
import TorrentEngine.MTTorrentManager;
import TorrentEngine.MTTorrentObserver;
import TorrentEngine.Statistics;
import data.LocalizationSupport;
import data.MEStatistics;
import data.MTPreferences;
import data.MTRMSManager;
import java.io.IOException;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Image;

/**
 *
 * @author Tyrael
 */
public class MTUIManager implements MTTorrentObserver
{
    private MobTorrentMidlet midlet;
    private MTTorrentManager torrentManager;
    private MTListTorrents listTorrents = null;
    private MTFormSettings formSettings = null;
    private MTCanvasDownloadState canvasDownloadState = null;
    private MTFormProperties formProperties = null;
    private MTFormFileCreateState formFileCreateState = null;
    private MTListFiles listFiles = null;
    private MTFormAbout formAbout = null;
    private MTFormHelp formHelp = null;
    private MTFormUpdate formUpdate = null;
    private int currentScreenID = -1;
    private Image iconComplete = null;
    private Image iconDownloading = null;
    private Image iconFailed = null;
    private Image iconParsingCreating = null;
    private Image iconPaused = null;
    private Image iconUploading = null;
    private Image iconWaiting = null;

    public MTUIManager(MobTorrentMidlet aMidlet)
    {
        midlet = aMidlet;

        Statistics stats = null;
        if(MTPreferences.EnableStats)
        {
            stats = new MEStatistics();
        }

        torrentManager = new MTTorrentManager(this, stats);
    }

    public void showScreen(int aScreenID)
    {
        currentScreenID = aScreenID;
        switch (aScreenID)
        {
            case MTListTorrents.ScreenID:
            {
                if (listTorrents == null)
                {
                    listTorrents = new MTListTorrents(this);
                }
                show(listTorrents);
                break;
            }
            case MTFormSettings.ScreenID:
            {
                if (formSettings == null)
                {
                    formSettings = new MTFormSettings(
                        LocalizationSupport.getMessage("title_formSettings"), this);
                }
                show(formSettings);
                break;
            }
            case MTCanvasDownloadState.ScreenID:
            {
                if (torrentManager.simpleTorrentAtIndex(listTorrents.getSelectedIndex()).isValid())
                {
                    if (canvasDownloadState == null)
                    {
                        canvasDownloadState = new MTCanvasDownloadState(
                            LocalizationSupport.getMessage("title_formDownloadState"), this);
                    }
                    canvasDownloadState.initialize(
                        torrentManager.simpleTorrentAtIndex(listTorrents.getSelectedIndex()));
                    show(canvasDownloadState);
                }
                else
                {
                    if (formFileCreateState == null)
                    {
                        formFileCreateState = new MTFormFileCreateState(
                            LocalizationSupport.getMessage("title_formFileCreateState"), this);
                    }
                    currentScreenID = MTFormFileCreateState.ScreenID;
                    show(formFileCreateState);
                }
                break;
            }
            case MTFormProperties.ScreenID:
            {
                if (formProperties == null)
                {
                    formProperties = new MTFormProperties(
                        LocalizationSupport.getMessage("title_formProperties"), this);
                }
                formProperties.initialize(
                    torrentManager.simpleTorrentAtIndex(listTorrents.getSelectedIndex()));
                show(formProperties);
                break;
            }
            case MTListFiles.ScreenID:
            {
                if (listFiles == null)
                {
                    listFiles = new MTListFiles(
                        LocalizationSupport.getMessage("title_listFiles"), this);
                }
                listFiles.refreshFilesData(
                    torrentManager.simpleTorrentAtIndex(listTorrents.getSelectedIndex()));
                show(listFiles);
                break;
            }
            case MTFormFileCreateState.ScreenID:
            {
                if (formFileCreateState == null)
                {
                    formFileCreateState = new MTFormFileCreateState(
                        LocalizationSupport.getMessage("title_formFileCreateState"), this);
                }
                currentScreenID = MTFormFileCreateState.ScreenID;
                show(formFileCreateState);
                break;
            }
            case MTFormAbout.ScreenID:
            {
                if (formAbout == null)
                {
                    formAbout = new MTFormAbout(this);
                }
                currentScreenID = MTFormAbout.ScreenID;
                show(formAbout);
                break;
            }
            case MTFormHelp.ScreenID:
            {
                if (formHelp == null)
                {
                    formHelp = new MTFormHelp(this);
                }
                currentScreenID = MTFormHelp.ScreenID;
                show(formHelp);
                break;
            }
            case MTFormUpdate.ScreenID:
            {
                if (formUpdate == null)
                {
                    formUpdate = new MTFormUpdate(this);
                }
                currentScreenID = MTFormUpdate.ScreenID;
                show(formUpdate);
                break;
            }
            default:
            {
                if (listTorrents == null)
                {
                    listTorrents = new MTListTorrents(this);
                }
                show(listTorrents);
                break;
            }
        }
    }

    public void show(Displayable aScreen)
    {
        Display.getDisplay(getMidlet()).setCurrent(aScreen);
    }

    public void exit()
    {
        getMidlet().destroyApp(true);
        getMidlet().notifyDestroyed();
    }

    public void endTorrentManager()
    {
        if (torrentManager != null)
        {
            torrentManager.endTorrentManager();
        }
    }

    public MTTorrentManager getTorrentManager()
    {
        return torrentManager;
    }

    // shows an alert message and we can set the next screen after the alert
    public void showMessage(String aMessage)
    {
        Alert alert = new Alert("MobTorrent", aMessage, null, AlertType.ERROR);
        alert.setTimeout(Alert.FOREVER);
        Display.getDisplay(getMidlet()).setCurrent(alert,
            Display.getDisplay(getMidlet()).getCurrent());
    }

    /**
     * @return the midlet
     */
    public MobTorrentMidlet getMidlet() {
        return midlet;
    }

    // --- Singleton Image getters

    public Image getIconComplete() {
        if (iconComplete == null)
        {
            try {
                iconComplete = Image.createImage("/resources/complete.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconComplete;
    }

    public Image getIconDownloading() {
        if (iconDownloading == null)
        {
            try {
                iconDownloading = Image.createImage("/resources/downloading.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconDownloading;
    }

    public Image getIconFailed() {
        if (iconFailed == null)
        {
            try {
                iconFailed = Image.createImage("/resources/failed.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconFailed;
    }

    private Image getIconParsingCreating() {
        if (iconParsingCreating == null)
        {
            try {
                iconParsingCreating = Image.createImage("/resources/parsingcreating.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconParsingCreating;
    }

    public Image getIconPaused() {
        if (iconPaused == null)
        {
            try {
                iconPaused = Image.createImage("/resources/paused.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconPaused;
    }

    private Image getIconUploading() {
        if (iconUploading == null)
        {
            try {
                iconUploading = Image.createImage("/resources/uploading.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconUploading;
    }

    private Image getIconWaiting() {
        if (iconWaiting == null)
        {
            try {
                iconWaiting = Image.createImage("/resources/waiting.png");
            } catch (IOException ex) {
                showMessage(ex.getMessage());
            }
        }
        return iconWaiting;
    }

    // ---

    // --- Torrent specific functions

    public void startTorrent(int aIndex)
    {
        torrentManager.simpleTorrentAtIndex(aIndex).start();
    }

    public void stopTorrent(int aIndex)
    {
        MTTorrent tempTorrent = torrentManager.simpleTorrentAtIndex(aIndex);
        if (tempTorrent != null)
        {
            tempTorrent.stop(true);
        }
    }

    public void removeTorrent(int aIndex)
    {
        torrentManager.simpleTorrentAtIndex(aIndex).close();
    }

    public void openNewTorrent(final String aSelectedFileName,
        final String aSelectedFileNameWithoutPath, final boolean aSavedTorrent,
        final byte[] aBitField, final String aDownloadFolder)
    {
        new Thread() {
            public void run()
            {
                MTOpenTorrentResult openTorrentResult = torrentManager.openTorrent(aSelectedFileName, aSelectedFileNameWithoutPath,
                    aSavedTorrent, aBitField, aDownloadFolder);

                switch (openTorrentResult.getOpenResult())
                {
                    case MTErrorCodes.ErrNone:
                    {
                        openTorrentResult.getOpenedTorrent().start();
                        break;
                    }
                    case MTErrorCodes.ErrAlreadyExists:
                    {
                        torrentManager.removeTorrentFromVector(openTorrentResult.getOpenedTorrent());
                        showMessage(LocalizationSupport.getMessage("text_alreadyAdded"));
                        break;
                    }
                    case MTErrorCodes.ErrNoFreeSize:
                    {
                        torrentManager.removeTorrentFromVector(openTorrentResult.getOpenedTorrent());
                        showMessage(LocalizationSupport.getMessage("text_errorNotEnoughFreeSize"));
                        break;
                    }
                    case MTErrorCodes.ErrFileHandling:
                    {
                        torrentManager.removeTorrentFromVector(openTorrentResult.getOpenedTorrent());
                        showMessage(LocalizationSupport.getMessage("text_errorFileHandling"));
                        break;
                    }
                    default:
                    {
                        torrentManager.removeTorrentFromVector(openTorrentResult.getOpenedTorrent());
                        showMessage(LocalizationSupport.getMessage("text_errorFailedToOpen"));
                        break;
                    }
                }

            }
        }.start();
    }

    public void torrentChanged(final MTTorrent aTorrent, final int index,
        final int aEventFlags)
    {
        try
        {
            // UI handling
            switch (aEventFlags)
            {
                case MTTorrentObserver.EMTEventDownloadedBytesChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateDownloadPercent(aTorrent.getDownloadPercent());
                    }
                    else if (currentScreenID == MTListTorrents.ScreenID && index == listTorrents.getSelectedIndex())
                    {
                        listTorrents.setTitle(
                                MTStringFormatter.getFormattedPercent(aTorrent.getDownloadPercent()) + " " +
                                LocalizationSupport.getMessage("text_down")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageBytesPerSecond())+"/" +
                                LocalizationSupport.getMessage("text_sec")+" "+
                                LocalizationSupport.getMessage("text_up")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageUploadedBytesPerSecond())+"/"+
                                LocalizationSupport.getMessage("text_sec"));
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventDownloadSpeedChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateDownloadSpeed(aTorrent.getAvarageBytesPerSecond(),aTorrent.getAvarageUploadedBytesPerSecond());
                    }
                    if (currentScreenID == MTListTorrents.ScreenID && index == listTorrents.getSelectedIndex())
                    {
                        listTorrents.setTitle(
                                MTStringFormatter.getFormattedPercent(aTorrent.getDownloadPercent()) + " " +
                                LocalizationSupport.getMessage("text_down")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageBytesPerSecond())+"/" +
                                LocalizationSupport.getMessage("text_sec")+" "+
                                LocalizationSupport.getMessage("text_up")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageUploadedBytesPerSecond())+"/"+
                                LocalizationSupport.getMessage("text_sec"));
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventUploadedBytesChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateDownloadPercent(aTorrent.getDownloadPercent());
                    }
                    if (currentScreenID == MTListTorrents.ScreenID && index == listTorrents.getSelectedIndex())
                    {
                        listTorrents.setTitle(
                                MTStringFormatter.getFormattedPercent(aTorrent.getDownloadPercent()) + " " +
                                LocalizationSupport.getMessage("text_down")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageBytesPerSecond())+"/" +
                                LocalizationSupport.getMessage("text_sec")+" "+
                                LocalizationSupport.getMessage("text_up")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageUploadedBytesPerSecond())+"/"+
                                LocalizationSupport.getMessage("text_sec"));
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventUploadSpeedChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateDownloadSpeed(aTorrent.getAvarageBytesPerSecond(),aTorrent.getAvarageUploadedBytesPerSecond());
                    }
                    if (currentScreenID == MTListTorrents.ScreenID && index == listTorrents.getSelectedIndex())
                    {
                        listTorrents.setTitle(
                                MTStringFormatter.getFormattedPercent(aTorrent.getDownloadPercent()) + " " +
                                LocalizationSupport.getMessage("text_down")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageBytesPerSecond())+"/" +
                                LocalizationSupport.getMessage("text_sec")+" "+
                                LocalizationSupport.getMessage("text_up")+": "+
                                MTStringFormatter.getFormattedFileLength((long)aTorrent.getAvarageUploadedBytesPerSecond())+"/"+
                                LocalizationSupport.getMessage("text_sec"));
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventConnectionsChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateConnections(aTorrent.getPeerWireConnectionCount(),aTorrent.getIncomingConnectionsNum());
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventPeersChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateConnections(aTorrent.getPeerWireConnectionCount(),aTorrent.getIncomingConnectionsNum());
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventIncomingConnectionsChanged:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updateConnections(aTorrent.getPeerWireConnectionCount(),aTorrent.getIncomingConnectionsNum());
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventPieceDownloaded:
                {
                    if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                    {
                        canvasDownloadState.updatePieceDownload();
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventTorrentStopped:
                {
                    if (currentScreenID == MTListTorrents.ScreenID && index != -1)
                    {
                        listTorrents.set(
                            index,aTorrent.getTorrentNameWithoutPath(),getIconFailed());
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventTorrentRemoved:
                {
                    if (currentScreenID == MTListTorrents.ScreenID)
                    {
                        listTorrents.delete(index);
                    }

                    // sets the visibility of the commands
                    listTorrents.setCommandsByState();
                    torrentManager.removeSimpleTorrentFromVector(index);

                    if (listTorrents.size() == 0)
                    {
                        listTorrents.setTitle(LocalizationSupport.getMessage("title_listTorrents"));
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventTorrentPaused:
                {
                    if (currentScreenID == MTListTorrents.ScreenID)
                    {
                        listTorrents.set(
                            index,aTorrent.getTorrentNameWithoutPath(), getIconPaused());
                    }
                    break;
                }
                case MTTorrentObserver.EMTEventTorrentFilesStateChanged:
                {
                    if (currentScreenID == MTListFiles.ScreenID)
                        listFiles.refreshFilesData(aTorrent);
                    break;
                }

                case MTTorrentObserver.EMTEventAutoSaveRequired:
                {
                    MTRMSManager.storeTorrentsToRMS(torrentManager);
                }
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
            MTLogger.writeLine("Error in torrentChanged(): "+e.getMessage());
        }
    }

    public void torrentMainChanged(final MTTorrent aTorrent,
        final int index, final int aMainEventFlags)
    {
        if (index != -1)
        {
            try
            {
                switch (aMainEventFlags)
                {
                    case MTTorrentObserver.EMTMainEventTorrentNotDuplicated:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.append(aTorrent.getTorrentNameWithoutPath(), getIconParsingCreating());
                            // sets the visibility of the commands
                            listTorrents.setCommandsByState();
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentTrackerConnecting:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.set(index,aTorrent.getTorrentNameWithoutPath(),getIconWaiting());
                            if (listTorrents.getSelectedIndex() == index)
                            {
                                listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_trackerConnecting"));
                            }
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentTrackerConnected:
                    {
                        if (currentScreenID == MTListTorrents.ScreenID &&
                            listTorrents.getSelectedIndex() == index)
                        {
                            listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_trackerConnected"));
                        }
                        if (currentScreenID == MTCanvasDownloadState.ScreenID && listTorrents.getSelectedIndex()==index)
                        {
                            if(canvasDownloadState != null)
                                canvasDownloadState.repaint();
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentDownloading:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.set(index,aTorrent.getTorrentNameWithoutPath(),
                                getIconDownloading());
                            if (listTorrents.getSelectedIndex() == index)
                            {
                                listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_startDownload"));
                            }
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentComplete:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.set(index,aTorrent.getTorrentNameWithoutPath(),
                                getIconComplete());
                            if (listTorrents.getSelectedIndex() == index)
                            {
                                listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_completed"));
                            }
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentFailed:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.set(index,aTorrent.getTorrentNameWithoutPath(),
                                getIconFailed());
                            if (listTorrents.getSelectedIndex() == index)
                            {
                                listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_failed"));
                            }
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentUploadStarted:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.set(index,aTorrent.getTorrentNameWithoutPath(),
                                getIconUploading());
                            if (listTorrents.getSelectedIndex() == index)
                            {
                                listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_uploading"));
                            }
                        }
                        break;
                    }
                    case MTTorrentObserver.EMTMainEventTorrentUploadEnded:
                    {
                        if (listTorrents != null)
                        {
                            listTorrents.set(index,aTorrent.getTorrentNameWithoutPath(),
                                getIconComplete());
                            if (listTorrents.getSelectedIndex() == index)
                            {
                                listTorrents.setTitle(
                                    LocalizationSupport.getMessage("text_completed"));
                            }
                        }
                        break;
                    }
                }
            }
            catch(Exception e)
            {
                e.printStackTrace();
                MTLogger.writeLine("Error in torrentMainChanged(): "+e.getMessage());
            }
        }
    }

    public void openTorrentStateChanged(final int aMainEventFlags,
        final MTTorrent aTorrent, final String aFileName, final double aPercent)
    {
        if (currentScreenID == MTFormFileCreateState.ScreenID &&
            listTorrents.getSelectedIndex()==torrentManager.getTorrentIndex(aTorrent))
        {
            switch (aMainEventFlags)
            {
                case MTTorrentObserver.EMTOpenTorrentEventCreatingFileStatus:
                {
                    formFileCreateState.fileCreateStateChanged(aFileName,aPercent);
                    break;
                }
                case MTTorrentObserver.EMTOpenTorrentEventCreatingFilesFinished:
                {
                    showScreen(MTCanvasDownloadState.ScreenID);
                    break;
                }
            }
        }
    }

    public void statusChanged(final String aMessage)
    {
        //System.out.println(aMessage);
    }

    public void synchronizeAddressBooster()
    {
        torrentManager.setAddressBooster(MTPreferences.EnableAddressBooster);
    }

    // ---
}

